package com.byfan.springboottemplate.service.impl;

import com.byfan.springboottemplate.common.CommonResponse;
import com.byfan.springboottemplate.dao.FileDao;
import com.byfan.springboottemplate.exception.SpringBootTemplateException;
import com.byfan.springboottemplate.model.FileEntity;
import com.byfan.springboottemplate.service.IFileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * @ClassName: FileServiceImpl
 * @Description:
 * @Author: byfan
 * @Date: 2023/7/28
 */
@Slf4j
@Service
public class FileServiceImpl implements IFileService {

    @Value("${staticpath}")
    private String staticPath;

    @Autowired
    private FileDao fileDao;

    @Override
    public List<FileEntity> getAll() throws SpringBootTemplateException {
        return fileDao.findAll();
    }

    @Override
    public FileEntity upload(MultipartFile multipartFile) throws SpringBootTemplateException {
        String originalFilename = multipartFile.getOriginalFilename();
        String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
        log.info("upload file, fileName={}, fileType={}", originalFilename, fileType);

        String uuid = getUuid();
        String uuidFileName = uuid + fileType;
        try{
            File filePath = new File(staticPath);
            if (!filePath.isDirectory()){
                filePath.mkdir();
            }

            File saveFile = new File(staticPath + uuidFileName);
            OutputStream out = new FileOutputStream(saveFile);
            byte[] bytes = multipartFile.getBytes();
            out.write(bytes);
            out.close();

            FileEntity entity = new FileEntity();
            entity.setPath(uuidFileName);
            entity.setName(originalFilename);

            return fileDao.save(entity);

        }catch (IOException e) {
            e.printStackTrace();
            throw new SpringBootTemplateException("文件上传失败");
        }

    }

    @Override
    public void delete(Long id) throws SpringBootTemplateException {
        log.info("delete file, id={}", id);
        if (null == id) {
            log.error("delete id is null");
            throw new SpringBootTemplateException(CommonResponse.PARAM_ERROR, "id is null");
        }

        Optional<FileEntity> one = fileDao.findById(id);
        if (one.isPresent()){
            File deleteFile = new File(staticPath + one.get().getPath());
            if (!deleteFile.exists()) {
                log.error("delete file is not exist");
                throw new SpringBootTemplateException(CommonResponse.RESOURCE_NOT_EXIST, "文件不存在");
            }
            deleteFile.delete();
            fileDao.deleteById(id);
        } else {
            throw new SpringBootTemplateException(CommonResponse.RESOURCE_NOT_EXIST, "文件在数据库中不存在");
        }
    }

    @Override
    public void delete(String path) throws SpringBootTemplateException {
        log.info("delete file, path={}", path);
        if (StringUtils.isBlank(path)) {
            log.error("delete path is null");
            throw new SpringBootTemplateException(CommonResponse.PARAM_ERROR, "path is null");
        }

        FileEntity fileEntity = new FileEntity();
        fileEntity.setPath(path);


        Optional<FileEntity> one = fileDao.findOne(Example.of(fileEntity));
        if (one.isPresent()){
            File deleteFile = new File(staticPath + path);
            if (!deleteFile.exists()) {
                log.error("delete file is not exist");
                throw new SpringBootTemplateException(CommonResponse.RESOURCE_NOT_EXIST, "文件不存在");
            }
            deleteFile.delete();
            fileDao.delete(fileEntity);
        } else {
            throw new SpringBootTemplateException(CommonResponse.RESOURCE_NOT_EXIST, "文件在数据库中不存在");
        }

    }

    @Override
    public void download(String path) throws SpringBootTemplateException {
        log.info("download file, path={}", path);
        if (StringUtils.isBlank(path)) {
            log.error("download path is null");
            throw new SpringBootTemplateException(CommonResponse.PARAM_ERROR, "path is null");
        }

        FileEntity fileEntity = new FileEntity();
        fileEntity.setPath(path);

        Optional<FileEntity> one = fileDao.findOne(Example.of(fileEntity));
        if (one.isPresent()){
            File downloadFile = new File(staticPath + path);
            if (!downloadFile.exists()) {
                log.error("download file {} is not exist", path);
                throw new SpringBootTemplateException(CommonResponse.RESOURCE_NOT_EXIST, "文件不存在");
            }

            try {
                ServletRequestAttributes requestAttributes =
                        (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletResponse response = requestAttributes.getResponse();
                response.setHeader("content-type", "application/octet-stream");
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=" + one.get().getName());
                InputStream inputStream = null;
                inputStream = downloadFile.toURL().openStream();
                IOUtils.copy(inputStream, response.getOutputStream());
            } catch (IOException e) {
                log.error("download file {} error", path, e);
                throw new SpringBootTemplateException("下载文件失败");
            }
        } else {
            throw new SpringBootTemplateException(CommonResponse.RESOURCE_NOT_EXIST, "文件在数据库中不存在");
        }
    }

    @Override
    public void download(Long id, HttpServletResponse response) throws SpringBootTemplateException {
        log.info("download file, id={}", id);
        if (null == id) {
            log.error("download id is null");
            throw new SpringBootTemplateException(CommonResponse.PARAM_ERROR, "id is null");
        }

        Optional<FileEntity> one = fileDao.findById(id);
        if (one.isPresent()){
            String path = one.get().getPath();
            File downloadFile = new File(staticPath + one.get().getPath());
            if (!downloadFile.exists()) {
                log.error("download file id={}, path={} is not exist", id, one.get().getPath());
                throw new SpringBootTemplateException(CommonResponse.RESOURCE_NOT_EXIST, "文件不存在");
            }
            try {
                response.setHeader("content-type", "application/octet-stream");
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=" + one.get().getName());
                InputStream inputStream = null;
                inputStream = downloadFile.toURL().openStream();
                IOUtils.copy(inputStream, response.getOutputStream());
            } catch (IOException e) {
                log.error("download file {} error", path, e);
                throw new SpringBootTemplateException("下载文件失败");
            }
        } else {
            throw new SpringBootTemplateException(CommonResponse.RESOURCE_NOT_EXIST, "文件在数据库中不存在");
        }
    }


    public String getUuid(){
        String uuid = UUID.randomUUID().toString();
        String[] split = uuid.split("-");
        String result = "";
        for (String s : split){
            result += s;
        }
        return result;
    }
}
